mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 10:11:41 -05:00
Update scheme for special export methods.
Export all saved contacts.
This commit is contained in:
parent
241fee80a7
commit
9d02e539c8
11 changed files with 159 additions and 50 deletions
|
@ -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;
|
inputWebDocument#9bed434d url:string size:int mime_type:string attributes:Vector<DocumentAttribute> = InputWebDocument;
|
||||||
|
|
||||||
inputWebFileLocation#c239d686 url:string access_hash:long = InputWebFileLocation;
|
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;
|
upload.webFile#21e753bc size:int mime_type:string file_type:storage.FileType mtime:int bytes:bytes = upload.WebFile;
|
||||||
|
|
||||||
|
@ -1014,6 +1012,10 @@ account.sentEmailCode#811f854f email_pattern:string length:int = account.SentEma
|
||||||
help.deepLinkInfoEmpty#66afa166 = help.DeepLinkInfo;
|
help.deepLinkInfoEmpty#66afa166 = help.DeepLinkInfo;
|
||||||
help.deepLinkInfo#6a4ee832 flags:# update_app:flags.0?true message:string entities:flags.1?Vector<MessageEntity> = 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---
|
---functions---
|
||||||
|
|
||||||
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
|
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
|
||||||
|
@ -1021,13 +1023,13 @@ 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;
|
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;
|
invokeWithLayer#da9b0d0d {X:Type} layer:int query:!X = X;
|
||||||
invokeWithoutUpdates#bf9459b7 {X:Type} 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.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.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.signIn#bcd51581 phone_number:string phone_code_hash:string phone_code:string = auth.Authorization;
|
||||||
auth.logOut#5717da40 = Bool;
|
auth.logOut#5717da40 = Bool;
|
||||||
auth.resetAuthorizations#9fab0d1a = Bool;
|
auth.resetAuthorizations#9fab0d1a = Bool;
|
||||||
auth.sendInvites#771c1d97 phone_numbers:Vector<string> message:string = Bool;
|
|
||||||
auth.exportAuthorization#e5bfffcd dc_id:int = auth.ExportedAuthorization;
|
auth.exportAuthorization#e5bfffcd dc_id:int = auth.ExportedAuthorization;
|
||||||
auth.importAuthorization#e3ef9613 id:int bytes:bytes = auth.Authorization;
|
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;
|
auth.bindTempAuthKey#cdd42a05 perm_auth_key_id:long nonce:long expires_at:int encrypted_message:bytes = Bool;
|
||||||
|
@ -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.verifyPhone#4dd3a7f6 phone_number:string phone_code_hash:string phone_code:string = Bool;
|
||||||
account.sendVerifyEmailCode#7011509f email:string = account.SentEmailCode;
|
account.sendVerifyEmailCode#7011509f email:string = account.SentEmailCode;
|
||||||
account.verifyEmail#ecba39db email:string code:string = Bool;
|
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.getUsers#d91a548 id:Vector<InputUser> = Vector<User>;
|
||||||
users.getFullUser#ca30a5b1 id:InputUser = UserFull;
|
users.getFullUser#ca30a5b1 id:InputUser = UserFull;
|
||||||
|
@ -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.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.resetTopPeerRating#1ae373ac category:TopPeerCategory peer:InputPeer = Bool;
|
||||||
contacts.resetSaved#879537f1 = Bool;
|
contacts.resetSaved#879537f1 = Bool;
|
||||||
|
contacts.getSaved#82f1e39f = Vector<SavedContact>;
|
||||||
|
|
||||||
messages.getMessages#63c66506 id:Vector<InputMessage> = messages.Messages;
|
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;
|
messages.getDialogs#191ba9c5 flags:# exclude_pinned:flags.0?true offset_date:int offset_id:int offset_peer:InputPeer limit:int = messages.Dialogs;
|
||||||
|
|
|
@ -134,4 +134,7 @@ vector concatenate(SpanRange args) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Implemented in base/openssl_help.h
|
||||||
|
void set_random(span destination);
|
||||||
|
|
||||||
} // namespace bytes
|
} // namespace bytes
|
||||||
|
|
|
@ -826,6 +826,23 @@ ContactsList ParseContactsList(const MTPcontacts_Contacts &data) {
|
||||||
return result;
|
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) {
|
std::vector<int> SortedContactsIndices(const ContactsList &data) {
|
||||||
const auto names = ranges::view::all(
|
const auto names = ranges::view::all(
|
||||||
data.list
|
data.list
|
||||||
|
@ -890,14 +907,19 @@ DialogsInfo ParseDialogsInfo(const MTPmessages_Dialogs &data) {
|
||||||
const auto peerId = ParsePeerId(fields.vpeer);
|
const auto peerId = ParsePeerId(fields.vpeer);
|
||||||
const auto peerIt = peers.find(peerId);
|
const auto peerIt = peers.find(peerId);
|
||||||
if (peerIt != end(peers)) {
|
if (peerIt != end(peers)) {
|
||||||
|
using Type = DialogInfo::Type;
|
||||||
const auto &peer = peerIt->second;
|
const auto &peer = peerIt->second;
|
||||||
info.type = peer.user()
|
info.type = peer.user()
|
||||||
? DialogInfo::Type::Personal
|
? (peer.user()->isBot
|
||||||
: peer.chat()->broadcast
|
? Type::Bot
|
||||||
? DialogInfo::Type::Channel
|
: Type::Personal)
|
||||||
: peer.chat()->username.isEmpty()
|
: (peer.chat()->broadcast
|
||||||
? DialogInfo::Type::PrivateGroup
|
? (peer.chat()->username.isEmpty()
|
||||||
: DialogInfo::Type::PublicGroup;
|
? Type::PrivateChannel
|
||||||
|
: Type::PublicChannel)
|
||||||
|
: (peer.chat()->username.isEmpty()
|
||||||
|
? Type::PrivateGroup
|
||||||
|
: Type::PublicGroup));
|
||||||
info.name = peer.name();
|
info.name = peer.name();
|
||||||
info.input = peer.input();
|
info.input = peer.input();
|
||||||
}
|
}
|
||||||
|
@ -940,6 +962,9 @@ Utf8String FormatDateTime(
|
||||||
QChar dateSeparator,
|
QChar dateSeparator,
|
||||||
QChar timeSeparator,
|
QChar timeSeparator,
|
||||||
QChar separator) {
|
QChar separator) {
|
||||||
|
if (!date) {
|
||||||
|
return Utf8String();
|
||||||
|
}
|
||||||
const auto value = QDateTime::fromTime_t(date);
|
const auto value = QDateTime::fromTime_t(date);
|
||||||
return (QString("%1") + dateSeparator + "%2" + dateSeparator + "%3"
|
return (QString("%1") + dateSeparator + "%2" + dateSeparator + "%3"
|
||||||
+ separator + "%4" + timeSeparator + "%5" + timeSeparator + "%6"
|
+ separator + "%4" + timeSeparator + "%5" + timeSeparator + "%6"
|
||||||
|
|
|
@ -136,6 +136,7 @@ struct ContactInfo {
|
||||||
Utf8String firstName;
|
Utf8String firstName;
|
||||||
Utf8String lastName;
|
Utf8String lastName;
|
||||||
Utf8String phoneNumber;
|
Utf8String phoneNumber;
|
||||||
|
TimeId date = 0;
|
||||||
|
|
||||||
Utf8String name() const;
|
Utf8String name() const;
|
||||||
};
|
};
|
||||||
|
@ -196,6 +197,7 @@ struct ContactsList {
|
||||||
};
|
};
|
||||||
|
|
||||||
ContactsList ParseContactsList(const MTPcontacts_Contacts &data);
|
ContactsList ParseContactsList(const MTPcontacts_Contacts &data);
|
||||||
|
ContactsList ParseContactsList(const MTPVector<MTPSavedContact> &data);
|
||||||
std::vector<int> SortedContactsIndices(const ContactsList &data);
|
std::vector<int> SortedContactsIndices(const ContactsList &data);
|
||||||
|
|
||||||
struct Session {
|
struct Session {
|
||||||
|
@ -394,9 +396,11 @@ struct DialogInfo {
|
||||||
enum class Type {
|
enum class Type {
|
||||||
Unknown,
|
Unknown,
|
||||||
Personal,
|
Personal,
|
||||||
|
Bot,
|
||||||
PrivateGroup,
|
PrivateGroup,
|
||||||
PublicGroup,
|
PublicGroup,
|
||||||
Channel,
|
PrivateChannel,
|
||||||
|
PublicChannel,
|
||||||
};
|
};
|
||||||
Type type = Type::Unknown;
|
Type type = Type::Unknown;
|
||||||
Utf8String name;
|
Utf8String name;
|
||||||
|
|
|
@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "export/data/export_data_types.h"
|
#include "export/data/export_data_types.h"
|
||||||
#include "export/output/export_output_file.h"
|
#include "export/output/export_output_file.h"
|
||||||
#include "mtproto/rpc_sender.h"
|
#include "mtproto/rpc_sender.h"
|
||||||
|
#include "base/bytes.h"
|
||||||
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
|
||||||
|
@ -23,6 +24,7 @@ constexpr auto kFileRequestsCount = 2;
|
||||||
constexpr auto kFileNextRequestDelay = TimeMs(20);
|
constexpr auto kFileNextRequestDelay = TimeMs(20);
|
||||||
constexpr auto kChatsSliceLimit = 100;
|
constexpr auto kChatsSliceLimit = 100;
|
||||||
constexpr auto kMessagesSliceLimit = 100;
|
constexpr auto kMessagesSliceLimit = 100;
|
||||||
|
constexpr auto kFileMaxSize = 1500 * 1024 * 1024;
|
||||||
|
|
||||||
bool WillLoadFile(const Data::File &file) {
|
bool WillLoadFile(const Data::File &file) {
|
||||||
return file.relativePath.isEmpty()
|
return file.relativePath.isEmpty()
|
||||||
|
@ -102,23 +104,29 @@ ApiWrap::DialogsProcess::Single::Single(const Data::DialogInfo &info)
|
||||||
|
|
||||||
template <typename Request>
|
template <typename Request>
|
||||||
auto ApiWrap::mainRequest(Request &&request) {
|
auto ApiWrap::mainRequest(Request &&request) {
|
||||||
return std::move(_mtp.request(
|
Expects(_takeoutId.has_value());
|
||||||
std::move(request)
|
|
||||||
).fail([=](RPCError &&result) {
|
return std::move(_mtp.request(MTPInvokeWithTakeout<Request>(
|
||||||
|
MTP_long(*_takeoutId),
|
||||||
|
request
|
||||||
|
)).fail([=](RPCError &&result) {
|
||||||
error(std::move(result));
|
error(std::move(result));
|
||||||
}).toDC(MTP::ShiftDcId(0, MTP::kExportDcShift)));
|
}).toDC(MTP::ShiftDcId(0, MTP::kExportDcShift)));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ApiWrap::fileRequest(const Data::FileLocation &location, int offset) {
|
auto ApiWrap::fileRequest(const Data::FileLocation &location, int offset) {
|
||||||
Expects(location.dcId != 0);
|
Expects(location.dcId != 0);
|
||||||
|
Expects(_takeoutId.has_value());
|
||||||
|
|
||||||
return std::move(_mtp.request(MTPupload_GetFile(
|
return std::move(_mtp.request(MTPInvokeWithTakeout<MTPupload_GetFile>(
|
||||||
|
MTP_long(*_takeoutId),
|
||||||
|
MTPupload_GetFile(
|
||||||
location.data,
|
location.data,
|
||||||
MTP_int(offset),
|
MTP_int(offset),
|
||||||
MTP_int(kFileChunkSize)
|
MTP_int(kFileChunkSize))
|
||||||
)).fail([=](RPCError &&result) {
|
)).fail([=](RPCError &&result) {
|
||||||
error(std::move(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)
|
ApiWrap::ApiWrap(Fn<void(FnMut<void()>)> runner)
|
||||||
|
@ -129,10 +137,57 @@ rpl::producer<RPCError> ApiWrap::errors() const {
|
||||||
return _errors.events();
|
return _errors.events();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApiWrap::startExport(const Settings &settings) {
|
void ApiWrap::startExport(
|
||||||
|
const Settings &settings,
|
||||||
|
FnMut<void()> done) {
|
||||||
Expects(_settings == nullptr);
|
Expects(_settings == nullptr);
|
||||||
|
|
||||||
_settings = std::make_unique<Settings>(settings);
|
_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) {
|
void ApiWrap::requestPersonalInfo(FnMut<void(Data::PersonalInfo&&)> done) {
|
||||||
|
@ -266,16 +321,10 @@ void ApiWrap::finishUserpics() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApiWrap::requestContacts(FnMut<void(Data::ContactsList&&)> done) {
|
void ApiWrap::requestContacts(FnMut<void(Data::ContactsList&&)> done) {
|
||||||
const auto hash = 0;
|
mainRequest(MTPcontacts_GetSaved(
|
||||||
mainRequest(MTPcontacts_GetContacts(
|
|
||||||
MTP_int(hash)
|
|
||||||
)).done([=, done = std::move(done)](
|
)).done([=, done = std::move(done)](
|
||||||
const MTPcontacts_Contacts &result) mutable {
|
const MTPVector<MTPSavedContact> &result) mutable {
|
||||||
if (result.type() == mtpc_contacts_contacts) {
|
|
||||||
done(Data::ParseContactsList(result));
|
done(Data::ParseContactsList(result));
|
||||||
} else {
|
|
||||||
error("Bad contacts type.");
|
|
||||||
}
|
|
||||||
}).send();
|
}).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,12 +403,16 @@ void ApiWrap::appendDialogsSlice(Data::DialogsInfo &&info) {
|
||||||
switch (info.type) {
|
switch (info.type) {
|
||||||
case DialogType::Personal:
|
case DialogType::Personal:
|
||||||
return Settings::Type::PersonalChats;
|
return Settings::Type::PersonalChats;
|
||||||
|
case DialogType::Bot:
|
||||||
|
return Settings::Type::BotChats;
|
||||||
case DialogType::PrivateGroup:
|
case DialogType::PrivateGroup:
|
||||||
return Settings::Type::PrivateGroups;
|
return Settings::Type::PrivateGroups;
|
||||||
case DialogType::PublicGroup:
|
case DialogType::PublicGroup:
|
||||||
return Settings::Type::PublicGroups;
|
return Settings::Type::PublicGroups;
|
||||||
case DialogType::Channel:
|
case DialogType::PrivateChannel:
|
||||||
return Settings::Type::MyChannels;
|
return Settings::Type::PrivateChannels;
|
||||||
|
case DialogType::PublicChannel:
|
||||||
|
return Settings::Type::PublicChannels;
|
||||||
}
|
}
|
||||||
return Settings::Type(0);
|
return Settings::Type(0);
|
||||||
}();
|
}();
|
||||||
|
@ -536,6 +589,7 @@ void ApiWrap::loadFile(const Data::File &file, FnMut<void(QString)> done) {
|
||||||
_settings->path + relativePath);
|
_settings->path + relativePath);
|
||||||
_fileProcess->relativePath = relativePath;
|
_fileProcess->relativePath = relativePath;
|
||||||
_fileProcess->location = file.location;
|
_fileProcess->location = file.location;
|
||||||
|
_fileProcess->size = file.size;
|
||||||
_fileProcess->done = std::move(done);
|
_fileProcess->done = std::move(done);
|
||||||
|
|
||||||
if (!file.content.isEmpty()) {
|
if (!file.content.isEmpty()) {
|
||||||
|
|
|
@ -31,7 +31,9 @@ public:
|
||||||
|
|
||||||
rpl::producer<RPCError> errors() const;
|
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);
|
void requestPersonalInfo(FnMut<void(Data::PersonalInfo&&)> done);
|
||||||
|
|
||||||
|
@ -54,12 +56,16 @@ public:
|
||||||
~ApiWrap();
|
~ApiWrap();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void startMainSession(FnMut<void()> done);
|
||||||
|
|
||||||
void handleUserpicsSlice(const MTPphotos_Photos &result);
|
void handleUserpicsSlice(const MTPphotos_Photos &result);
|
||||||
void loadUserpicsFiles(Data::UserpicsSlice &&slice);
|
void loadUserpicsFiles(Data::UserpicsSlice &&slice);
|
||||||
void loadNextUserpic();
|
void loadNextUserpic();
|
||||||
void loadUserpicDone(const QString &relativePath);
|
void loadUserpicDone(const QString &relativePath);
|
||||||
void finishUserpics();
|
void finishUserpics();
|
||||||
|
|
||||||
|
void requestSavedContacts();
|
||||||
|
|
||||||
void requestDialogsSlice();
|
void requestDialogsSlice();
|
||||||
void appendDialogsSlice(Data::DialogsInfo &&info);
|
void appendDialogsSlice(Data::DialogsInfo &&info);
|
||||||
void finishDialogsList();
|
void finishDialogsList();
|
||||||
|
@ -88,6 +94,7 @@ private:
|
||||||
void error(const QString &text);
|
void error(const QString &text);
|
||||||
|
|
||||||
MTP::ConcurrentSender _mtp;
|
MTP::ConcurrentSender _mtp;
|
||||||
|
base::optional<uint64> _takeoutId;
|
||||||
|
|
||||||
std::unique_ptr<Settings> _settings;
|
std::unique_ptr<Settings> _settings;
|
||||||
MTPInputUser _user = MTP_inputUserSelf();
|
MTPInputUser _user = MTP_inputUserSelf();
|
||||||
|
|
|
@ -157,9 +157,10 @@ void Controller::startExport(const Settings &settings) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_writer = Output::CreateWriter(_settings.format);
|
_writer = Output::CreateWriter(_settings.format);
|
||||||
_api.startExport(_settings);
|
|
||||||
fillExportSteps();
|
fillExportSteps();
|
||||||
|
_api.startExport(_settings, [=] {
|
||||||
exportNext();
|
exportNext();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Controller::normalizePath() {
|
bool Controller::normalizePath() {
|
||||||
|
@ -207,9 +208,11 @@ void Controller::fillExportSteps() {
|
||||||
_steps.push_back(Step::Sessions);
|
_steps.push_back(Step::Sessions);
|
||||||
}
|
}
|
||||||
const auto dialogTypes = Type::PersonalChats
|
const auto dialogTypes = Type::PersonalChats
|
||||||
|
| Type::BotChats
|
||||||
| Type::PrivateGroups
|
| Type::PrivateGroups
|
||||||
| Type::PublicGroups
|
| Type::PublicGroups
|
||||||
| Type::MyChannels;
|
| Type::PrivateChannels
|
||||||
|
| Type::PublicChannels;
|
||||||
if (_settings.types & dialogTypes) {
|
if (_settings.types & dialogTypes) {
|
||||||
_steps.push_back(Step::Dialogs);
|
_steps.push_back(Step::Dialogs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,5 +28,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "platform/win/windows_range_v3_helpers.h"
|
#include "platform/win/windows_range_v3_helpers.h"
|
||||||
#endif // Q_OS_WIN
|
#endif // Q_OS_WIN
|
||||||
|
|
||||||
|
#include "base/flat_map.h"
|
||||||
|
#include "base/flat_set.h"
|
||||||
|
|
||||||
#include "scheme.h"
|
#include "scheme.h"
|
||||||
#include "logs.h"
|
#include "logs.h"
|
||||||
|
|
|
@ -37,14 +37,16 @@ struct MediaSettings {
|
||||||
|
|
||||||
struct Settings {
|
struct Settings {
|
||||||
enum class Type {
|
enum class Type {
|
||||||
PersonalInfo = 0x01,
|
PersonalInfo = 0x001,
|
||||||
Userpics = 0x02,
|
Userpics = 0x002,
|
||||||
Contacts = 0x04,
|
Contacts = 0x004,
|
||||||
Sessions = 0x08,
|
Sessions = 0x008,
|
||||||
PersonalChats = 0x10,
|
PersonalChats = 0x010,
|
||||||
PrivateGroups = 0x20,
|
BotChats = 0x020,
|
||||||
PublicGroups = 0x40,
|
PrivateGroups = 0x040,
|
||||||
MyChannels = 0x80,
|
PublicGroups = 0x080,
|
||||||
|
PrivateChannels = 0x100,
|
||||||
|
PublicChannels = 0x200,
|
||||||
};
|
};
|
||||||
using Types = base::flags<Type>;
|
using Types = base::flags<Type>;
|
||||||
friend inline constexpr auto is_flag_type(Type) { return true; };
|
friend inline constexpr auto is_flag_type(Type) { return true; };
|
||||||
|
|
|
@ -460,9 +460,7 @@ bool TextWriter::writeContactsList(const Data::ContactsList &data) {
|
||||||
list.reserve(data.list.size());
|
list.reserve(data.list.size());
|
||||||
for (const auto &index : Data::SortedContactsIndices(data)) {
|
for (const auto &index : Data::SortedContactsIndices(data)) {
|
||||||
const auto &contact = data.list[index];
|
const auto &contact = data.list[index];
|
||||||
if (!contact.userId) {
|
if (contact.firstName.isEmpty()
|
||||||
list.push_back("(user unavailable)" + kLineBreak);
|
|
||||||
} else if (contact.firstName.isEmpty()
|
|
||||||
&& contact.lastName.isEmpty()
|
&& contact.lastName.isEmpty()
|
||||||
&& contact.phoneNumber.isEmpty()) {
|
&& contact.phoneNumber.isEmpty()) {
|
||||||
list.push_back("(deleted user)" + kLineBreak);
|
list.push_back("(deleted user)" + kLineBreak);
|
||||||
|
@ -474,6 +472,7 @@ bool TextWriter::writeContactsList(const Data::ContactsList &data) {
|
||||||
"Phone number",
|
"Phone number",
|
||||||
Data::FormatPhoneNumber(contact.phoneNumber)
|
Data::FormatPhoneNumber(contact.phoneNumber)
|
||||||
},
|
},
|
||||||
|
{ "Date", Data::FormatDateTime(contact.date) }
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -539,10 +538,12 @@ bool TextWriter::writeDialogsStart(const Data::DialogsInfo &data) {
|
||||||
const auto TypeString = [](Type type) {
|
const auto TypeString = [](Type type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Type::Unknown: return "(unknown)";
|
case Type::Unknown: return "(unknown)";
|
||||||
case Type::Personal: return "Personal Chat";
|
case Type::Personal: return "Personal chat";
|
||||||
case Type::PrivateGroup: return "Private Group";
|
case Type::Bot: return "Bot chat";
|
||||||
case Type::PublicGroup: return "Public Group";
|
case Type::PrivateGroup: return "Private group";
|
||||||
case Type::Channel: return "Channel";
|
case Type::PublicGroup: return "Public group";
|
||||||
|
case Type::PrivateChannel: return "Private channel";
|
||||||
|
case Type::PublicChannel: return "Private channel";
|
||||||
}
|
}
|
||||||
Unexpected("Dialog type in TypeString.");
|
Unexpected("Dialog type in TypeString.");
|
||||||
};
|
};
|
||||||
|
@ -555,9 +556,11 @@ bool TextWriter::writeDialogsStart(const Data::DialogsInfo &data) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Type::Unknown: return "(unknown)";
|
case Type::Unknown: return "(unknown)";
|
||||||
case Type::Personal: return "(deleted user)";
|
case Type::Personal: return "(deleted user)";
|
||||||
|
case Type::Bot: return "(deleted bot)";
|
||||||
case Type::PrivateGroup:
|
case Type::PrivateGroup:
|
||||||
case Type::PublicGroup: return "(deleted group)";
|
case Type::PublicGroup: return "(deleted group)";
|
||||||
case Type::Channel: return "(deleted channel)";
|
case Type::PrivateChannel:
|
||||||
|
case Type::PublicChannel: return "(deleted channel)";
|
||||||
}
|
}
|
||||||
Unexpected("Dialog type in TypeString.");
|
Unexpected("Dialog type in TypeString.");
|
||||||
};
|
};
|
||||||
|
|
|
@ -31,6 +31,7 @@ constexpr auto kConfigDcShift = 0x01;
|
||||||
constexpr auto kLogoutDcShift = 0x02;
|
constexpr auto kLogoutDcShift = 0x02;
|
||||||
constexpr auto kUpdaterDcShift = 0x03;
|
constexpr auto kUpdaterDcShift = 0x03;
|
||||||
constexpr auto kExportDcShift = 0x04;
|
constexpr auto kExportDcShift = 0x04;
|
||||||
|
constexpr auto kExportMediaDcShift = 0x05;
|
||||||
constexpr auto kMaxMediaDcCount = 0x10;
|
constexpr auto kMaxMediaDcCount = 0x10;
|
||||||
constexpr auto kBaseDownloadDcShift = 0x10;
|
constexpr auto kBaseDownloadDcShift = 0x10;
|
||||||
constexpr auto kBaseUploadDcShift = 0x20;
|
constexpr auto kBaseUploadDcShift = 0x20;
|
||||||
|
|
Loading…
Add table
Reference in a new issue