Export sessions list.

This commit is contained in:
John Preston 2018-06-11 21:57:56 +03:00
parent cec8114b99
commit d3fdf433cd
6 changed files with 114 additions and 29 deletions

View File

@ -100,19 +100,18 @@ Photo ParsePhoto(const MTPPhoto &data, const QString &suggestedPath) {
}
Utf8String FormatDateTime(
const int32 date,
const QDateTime &date,
QChar dateSeparator,
QChar timeSeparator,
QChar separator) {
const auto value = QDateTime::fromTime_t(date);
return (QString("%1") + dateSeparator + "%2" + dateSeparator + "%3"
+ separator + "%4" + timeSeparator + "%5" + timeSeparator + "%6"
).arg(value.date().year()
).arg(value.date().month(), 2, 10, QChar('0')
).arg(value.date().day(), 2, 10, QChar('0')
).arg(value.time().hour(), 2, 10, QChar('0')
).arg(value.time().minute(), 2, 10, QChar('0')
).arg(value.time().second(), 2, 10, QChar('0')
).arg(date.date().year()
).arg(date.date().month(), 2, 10, QChar('0')
).arg(date.date().day(), 2, 10, QChar('0')
).arg(date.time().hour(), 2, 10, QChar('0')
).arg(date.time().minute(), 2, 10, QChar('0')
).arg(date.time().second(), 2, 10, QChar('0')
).toUtf8();
}
@ -200,6 +199,52 @@ ContactsList ParseContactsList(const MTPcontacts_Contacts &data) {
return result;
}
std::vector<int> SortedContactsIndices(const ContactsList &data) {
const auto names = ranges::view::all(
data.list
) | ranges::view::transform([](const Data::User &user) {
return (QString::fromUtf8(user.firstName)
+ ' '
+ QString::fromUtf8(user.lastName)).toLower();
}) | ranges::to_vector;
auto indices = ranges::view::ints(0, int(data.list.size()))
| ranges::to_vector;
ranges::sort(indices, [&](int i, int j) {
return names[i] < names[j];
});
return indices;
}
Session ParseSession(const MTPAuthorization &data) {
Expects(data.type() == mtpc_authorization);
const auto &fields = data.c_authorization();
auto result = Session();
result.platform = ParseString(fields.vplatform);
result.deviceModel = ParseString(fields.vdevice_model);
result.systemVersion = ParseString(fields.vsystem_version);
result.applicationName = ParseString(fields.vapp_name);
result.applicationVersion = ParseString(fields.vapp_version);
result.created = QDateTime::fromTime_t(fields.vdate_created.v);
result.lastActive = QDateTime::fromTime_t(fields.vdate_active.v);
result.ip = ParseString(fields.vip);
result.country = ParseString(fields.vcountry);
result.region = ParseString(fields.vregion);
return result;
}
SessionsList ParseSessionsList(const MTPaccount_Authorizations &data) {
Expects(data.type() == mtpc_account_authorizations);
auto result = SessionsList();
const auto &list = data.c_account_authorizations().vauthorizations.v;
for (const auto &session : list) {
result.list.push_back(ParseSession(session));
}
return result;
}
Utf8String FormatPhoneNumber(const Utf8String &phoneNumber) {
return phoneNumber.isEmpty()
? Utf8String()

View File

@ -86,6 +86,7 @@ struct ContactsList {
};
ContactsList ParseContactsList(const MTPcontacts_Contacts &data);
std::vector<int> SortedContactsIndices(const ContactsList &data);
struct Session {
Utf8String platform;
@ -104,6 +105,8 @@ struct SessionsList {
std::vector<Session> list;
};
SessionsList ParseSessionsList(const MTPaccount_Authorizations &data);
struct ChatsInfo {
int count = 0;
};
@ -127,11 +130,24 @@ struct MessagesSlice {
};
Utf8String FormatPhoneNumber(const Utf8String &phoneNumber);
Utf8String FormatDateTime(
const int32 date,
const QDateTime &date,
QChar dateSeparator = QChar('.'),
QChar timeSeparator = QChar(':'),
QChar separator = QChar(' '));
inline Utf8String FormatDateTime(
int32 date,
QChar dateSeparator = QChar('.'),
QChar timeSeparator = QChar(':'),
QChar separator = QChar(' ')) {
return FormatDateTime(
QDateTime::fromTime_t(date),
dateSeparator,
timeSeparator,
separator);
}
} // namespace Data
} // namespace Export

View File

@ -243,6 +243,14 @@ void ApiWrap::requestContacts(FnMut<void(Data::ContactsList&&)> done) {
}).send();
}
void ApiWrap::requestSessions(FnMut<void(Data::SessionsList&&)> done) {
mainRequest(MTPaccount_GetAuthorizations(
)).done([=, done = std::move(done)](
const MTPaccount_Authorizations &result) mutable {
done(Data::ParseSessionsList(result));
}).send();
}
void ApiWrap::loadFile(const Data::File &file, FnMut<void(QString)> done) {
Expects(_fileProcess == nullptr);

View File

@ -17,6 +17,7 @@ struct PersonalInfo;
struct UserpicsInfo;
struct UserpicsSlice;
struct ContactsList;
struct SessionsList;
} // namespace Data
class ApiWrap {
@ -36,6 +37,8 @@ public:
void requestContacts(FnMut<void(Data::ContactsList&&)> done);
void requestSessions(FnMut<void(Data::SessionsList&&)> done);
~ApiWrap();
private:

View File

@ -261,7 +261,10 @@ void Controller::exportContacts() {
}
void Controller::exportSessions() {
exportNext();
_api.requestSessions([=](Data::SessionsList &&result) {
_writer->writeSessionsList(result);
exportNext();
});
}
void Controller::exportChats() {

View File

@ -130,8 +130,7 @@ bool TextWriter::writeUserpicsSlice(const Data::UserpicsSlice &data) {
if (!userpic.date.isValid()) {
lines.append("(empty photo)");
} else {
lines.append(Data::FormatDateTime(userpic.date.toTime_t()));
lines.append(" - ");
lines.append(Data::FormatDateTime(userpic.date)).append(" - ");
if (userpic.image.relativePath.isEmpty()) {
lines.append("(file unavailable)");
} else {
@ -154,28 +153,13 @@ bool TextWriter::writeContactsList(const Data::ContactsList &data) {
return true;
}
// Get sorted by name indices.
const auto names = ranges::view::all(
data.list
) | ranges::view::transform([](const Data::User &user) {
return (QString::fromUtf8(user.firstName)
+ ' '
+ QString::fromUtf8(user.lastName)).toLower();
}) | ranges::to_vector;
auto indices = ranges::view::ints(0, int(data.list.size()))
| ranges::to_vector;
ranges::sort(indices, [&](int i, int j) {
return names[i] < names[j];
});
const auto header = "Contacts "
"(" + Data::NumberToString(data.list.size()) + ")"
+ kLineBreak
+ kLineBreak;
auto list = std::vector<QByteArray>();
list.reserve(data.list.size());
for (const auto &index : indices) {
for (const auto &index : Data::SortedContactsIndices(data)) {
const auto &contact = data.list[index];
if (!contact.id) {
list.push_back("(user unavailable)");
@ -199,7 +183,33 @@ bool TextWriter::writeContactsList(const Data::ContactsList &data) {
}
bool TextWriter::writeSessionsList(const Data::SessionsList &data) {
return true;
const auto header = "Sessions "
"(" + Data::NumberToString(data.list.size()) + ")"
+ kLineBreak
+ kLineBreak;
auto list = std::vector<QByteArray>();
list.reserve(data.list.size());
for (const auto &session : data.list) {
list.push_back(SerializeKeyValue({
{ "Last active", Data::FormatDateTime(session.lastActive) },
{ "Last IP address", session.ip },
{ "Last country", session.country },
{ "Last region", session.region },
{
"Application name",
(session.applicationName.isEmpty()
? Data::Utf8String("(unknown)")
: session.applicationName)
},
{ "Application version", session.applicationVersion },
{ "Device model", session.deviceModel },
{ "Platform", session.platform },
{ "System version", session.systemVersion },
{ "Created", Data::FormatDateTime(session.created) },
}));
}
const auto full = header + JoinList(kLineBreak, list) + kLineBreak;
return _result->writeBlock(full) == File::Result::Success;
}
bool TextWriter::writeChatsStart(const Data::ChatsInfo &data) {