2
0
mirror of https://github.com/kotatogram/kotatogram-desktop synced 2025-08-31 06:35:14 +00:00

Export chat messages text.

This commit is contained in:
John Preston
2018-06-13 16:12:36 +03:00
parent 35ffc03988
commit 2b36dd660b
10 changed files with 418 additions and 72 deletions

View File

@@ -17,6 +17,10 @@ namespace Output {
File::File(const QString &path) : _path(path) {
}
bool File::empty() const {
return !_offset;
}
File::Result File::writeBlock(const QByteArray &block) {
const auto result = writeBlockAttempt(block);
if (result != Result::Success) {

View File

@@ -20,6 +20,8 @@ class File {
public:
File(const QString &path);
bool empty() const;
enum class Result {
Success,
Error,

View File

@@ -29,7 +29,7 @@ void SerializeMultiline(
auto offset = 0;
do {
appendTo.append("> ");
appendTo.append(data + offset, newline).append(kLineBreak);
appendTo.append(data + offset, newline - offset).append(kLineBreak);
offset = newline + 1;
newline = value.indexOf('\n', offset);
} while (newline > 0);
@@ -89,7 +89,7 @@ bool TextWriter::start(const QString &folder) {
Expects(folder.endsWith('/'));
_folder = folder;
_result = std::make_unique<File>(_folder + "result.txt");
_result = fileWithRelativePath(mainFileRelativePath());
return true;
}
@@ -128,7 +128,7 @@ bool TextWriter::writeUserpicsSlice(const Data::UserpicsSlice &data) {
auto lines = QByteArray();
for (const auto &userpic : data.list) {
if (!userpic.date) {
lines.append("(empty photo)");
lines.append("(deleted photo)");
} else {
lines.append(Data::FormatDateTime(userpic.date)).append(" - ");
if (userpic.image.relativePath.isEmpty()) {
@@ -153,17 +153,17 @@ bool TextWriter::writeContactsList(const Data::ContactsList &data) {
return true;
}
const auto file = std::make_unique<File>(_folder + "contacts.txt");
const auto file = fileWithRelativePath("contacts.txt");
auto list = std::vector<QByteArray>();
list.reserve(data.list.size());
for (const auto &index : Data::SortedContactsIndices(data)) {
const auto &contact = data.list[index];
if (!contact.id) {
list.push_back("(user unavailable)");
list.push_back("(user unavailable)" + kLineBreak);
} else if (contact.firstName.isEmpty()
&& contact.lastName.isEmpty()
&& contact.phoneNumber.isEmpty()) {
list.push_back("(empty user)" + kLineBreak);
list.push_back("(deleted user)" + kLineBreak);
} else {
list.push_back(SerializeKeyValue({
{ "First name", contact.firstName },
@@ -192,7 +192,7 @@ bool TextWriter::writeSessionsList(const Data::SessionsList &data) {
return true;
}
const auto file = std::make_unique<File>(_folder + "sessions.txt");
const auto file = fileWithRelativePath("sessions.txt");
auto list = std::vector<QByteArray>();
list.reserve(data.list.size());
for (const auto &session : data.list) {
@@ -231,6 +231,8 @@ bool TextWriter::writeDialogsStart(const Data::DialogsInfo &data) {
return true;
}
_dialogsCount = data.list.size();
using Type = Data::DialogInfo::Type;
const auto TypeString = [](Type type) {
switch (type) {
@@ -242,20 +244,31 @@ bool TextWriter::writeDialogsStart(const Data::DialogsInfo &data) {
}
Unexpected("Dialog type in TypeString.");
};
const auto NameString = [](
const Data::Utf8String &name,
Type type) -> QByteArray {
if (!name.isEmpty()) {
return name;
}
switch (type) {
case Type::Unknown: return "(unknown)";
case Type::Personal: return "(deleted user)";
case Type::PrivateGroup:
case Type::PublicGroup: return "(deleted group)";
case Type::Channel: return "(deleted channel)";
}
Unexpected("Dialog type in TypeString.");
};
const auto digits = Data::NumberToString(data.list.size() - 1).size();
const auto file = std::make_unique<File>(_folder + "chats.txt");
const auto file = fileWithRelativePath("chats.txt");
auto list = std::vector<QByteArray>();
list.reserve(data.list.size());
auto index = 0;
for (const auto &dialog : data.list) {
auto number = Data::NumberToString(++index);
auto path = QByteArray("Chats/chat_");
for (auto i = number.size(); i < digits; ++i) {
path += '0';
}
path += number + ".txt";
const auto number = Data::NumberToString(++index, digits, '0');
const auto path = "Chats/chat_" + number + ".txt";
list.push_back(SerializeKeyValue({
{ "Name", dialog.name },
{ "Name", NameString(dialog.name, dialog.type) },
{ "Type", TypeString(dialog.type) },
{ "Content", path }
}));
@@ -273,14 +286,38 @@ bool TextWriter::writeDialogsStart(const Data::DialogsInfo &data) {
}
bool TextWriter::writeDialogStart(const Data::DialogInfo &data) {
Expects(_dialog == nullptr);
Expects(_dialogIndex < _dialogsCount);
const auto digits = Data::NumberToString(_dialogsCount - 1).size();
const auto number = Data::NumberToString(++_dialogIndex, digits, '0');
_dialog = fileWithRelativePath("Chats/chat_" + number + ".txt");
return true;
}
bool TextWriter::writeMessagesSlice(const Data::MessagesSlice &data) {
return true;
Expects(_dialog != nullptr);
auto list = std::vector<QByteArray>();
list.reserve(data.list.size());
auto index = 0;
for (const auto &message : data.list) {
list.push_back(SerializeKeyValue({
{ "ID", Data::NumberToString(message.id) },
{ "Date", Data::FormatDateTime(message.date) },
{ "Text", message.text }
}));
}
const auto full = _dialog->empty()
? JoinList(kLineBreak, list)
: kLineBreak + JoinList(kLineBreak, list);
return _dialog->writeBlock(full) == File::Result::Success;
}
bool TextWriter::writeDialogEnd() {
Expects(_dialog != nullptr);
_dialog = nullptr;
return true;
}
@@ -293,7 +330,20 @@ bool TextWriter::finish() {
}
QString TextWriter::mainFilePath() {
return _folder + "result.txt";
return pathWithRelativePath(mainFileRelativePath());
}
QString TextWriter::mainFileRelativePath() const {
return "result.txt";
}
QString TextWriter::pathWithRelativePath(const QString &path) const {
return _folder + path;
}
std::unique_ptr<File> TextWriter::fileWithRelativePath(
const QString &path) const {
return std::make_unique<File>(_folder + path);
}
} // namespace Output

View File

@@ -38,11 +38,19 @@ public:
QString mainFilePath() override;
private:
QString mainFileRelativePath() const;
QString pathWithRelativePath(const QString &path) const;
std::unique_ptr<File> fileWithRelativePath(const QString &path) const;
QString _folder;
std::unique_ptr<File> _result;
int _userpicsCount = 0;
int _dialogsCount = 0;
int _dialogIndex = 0;
std::unique_ptr<File> _dialog;
};
} // namespace Output