Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bulk export #103

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions project/WhatsApp Viewer.vcproj
Original file line number Diff line number Diff line change
Expand Up @@ -8052,6 +8052,10 @@
RelativePath="..\resources\chat_export.html.template"
>
</File>
<File
RelativePath="..\resources\chat_entry.html.template"
>
</File>
</Files>
<Globals>
</Globals>
Expand Down
5 changes: 5 additions & 0 deletions resources/Resources.rc
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,10 @@ BEGIN
MENUITEM "Decrypt .crypt&8...\tCtrl+8", ID_MENU_MAIN_FILE_DECRYPT_CRYPT8
MENUITEM "Decrypt .crypt&12...", ID_MENU_MAIN_FILE_DECRYPT_CRYPT12
MENUITEM SEPARATOR
MENUITEM "Export All Chats To Txt...", ID_MENU_MAIN_FILE_EXPORT_ALL_CHATS_TXT
MENUITEM "Export All Chats To Html...", ID_MENU_MAIN_FILE_EXPORT_ALL_CHATS_HTML
MENUITEM "Export All Chats To Json...", ID_MENU_MAIN_FILE_EXPORT_ALL_CHATS_JSON
MENUITEM SEPARATOR
MENUITEM "&Exit\tAlt+F4", ID_MENU_MAIN_FILE_EXIT
END
POPUP "&Help"
Expand Down Expand Up @@ -1918,6 +1922,7 @@ IDB_CLEAR_HOVER PNG "ClearHover.png"
//

IDR_CHAT_EXPORT_HTML_TEMPLATE HTML "chat_export.html.template"
IDR_CHAT_ENTRY_HTML_TEMPLATE HTML "chat_entry.html.template"


/////////////////////////////////////////////////////////////////////////////
Expand Down
16 changes: 16 additions & 0 deletions resources/chat_entry.html.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<div class="chat">
<div class="chat_header">
<div>
<span class="heading">%HEADING%</span>
</div>
<div>
<span class="contact">%CONTACT%</span>
</div>
<div>
<span class="contact">%CONTACT_NAME%</span>
</div>
</div>
<div class="messages">
%MESSAGES%
</div>
</div>
17 changes: 1 addition & 16 deletions resources/chat_export.html.template
Original file line number Diff line number Diff line change
Expand Up @@ -84,21 +84,6 @@
</head>

<body>
<div class="chat">
<div class="chat_header">
<div>
<span class="heading">%HEADING%</span>
</div>
<div>
<span class="contact">%CONTACT%</span>
</div>
<div>
<span class="contact">%CONTACT_NAME%</span>
</div>
</div>
<div class="messages">
%MESSAGES%
</div>
</div>
%CHAT_ENTRIES%
</body>
</html>
6 changes: 5 additions & 1 deletion resources/resource.h
Original file line number Diff line number Diff line change
Expand Up @@ -893,6 +893,7 @@
#define IDC_DECRYPT_CRYPT7_SELECT_KEY 1019
#define IDC_MAIN_MESSAGES_COUNT 1019
#define IDR_CHAT_EXPORT_HTML_TEMPLATE 1020
#define IDR_CHAT_ENTRY_HTML_TEMPLATE 1021
#define IDC_MAIN_MESSAGES_COUNT_LABEL 1020
#define ID_FILE_OPEN40001 40001
#define ID_MENU_MAIN_FILE_OPEN 40002
Expand All @@ -912,13 +913,16 @@
#define ID_ACCELERATOR_DECRYPT_CRYPT7 40019
#define ID_MENU_MAIN_FILE_DECRYPT_CRYPT8 40020
#define ID_MENU_MAIN_FILE_DECRYPT_CRYPT12 40021
#define ID_MENU_MAIN_FILE_EXPORT_ALL_CHATS_TXT 40022
#define ID_MENU_MAIN_FILE_EXPORT_ALL_CHATS_HTML 40023
#define ID_MENU_MAIN_FILE_EXPORT_ALL_CHATS_JSON 40024

// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 972
#define _APS_NEXT_COMMAND_VALUE 40022
#define _APS_NEXT_COMMAND_VALUE 40025
#define _APS_NEXT_CONTROL_VALUE 1021
#define _APS_NEXT_SYMED_VALUE 101
#endif
Expand Down
3 changes: 2 additions & 1 deletion source/Exporters/ChatExporter.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <string>
#include <vector>

class WhatsappChat;

Expand All @@ -10,5 +11,5 @@ class ChatExporter
ChatExporter() {}
virtual ~ChatExporter() {}

virtual void exportChat(WhatsappChat &chat, const std::string &filename) = 0;
virtual void exportChats(const std::vector<WhatsappChat *> &chats, const std::string &filename) = 0;
};
39 changes: 30 additions & 9 deletions source/Exporters/ChatExporterHtml.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@
#include "../Settings.h"
#include "../../resources/resource.h"

ChatExporterHtml::ChatExporterHtml(Settings &settings, const std::string &templateHtml)
: settings(settings), templateHtml(templateHtml)
ChatExporterHtml::ChatExporterHtml(Settings &settings, const std::string &templateHtml,
const std::string &entryTemplateHtml)
: settings(settings), templateHtml(templateHtml), entryTemplateHtml(entryTemplateHtml)
{
}

Expand Down Expand Up @@ -214,9 +215,8 @@ std::string ChatExporterHtml::buildEmoticonStyles(const std::set<int> &usedEmoti
return css.str();
}

void ChatExporterHtml::exportChat(WhatsappChat &chat, const std::string &filename)
std::string ChatExporterHtml::exportChat(WhatsappChat &chat, std::set<int> &usedEmoticons)
{
std::set<int> usedEmoticons;
std::string messages = buildMessages(chat, usedEmoticons);

std::string contact = chat.getKey();
Expand All @@ -232,20 +232,41 @@ void ChatExporterHtml::exportChat(WhatsappChat &chat, const std::string &filenam
contactName = "";
}

std::string html = entryTemplateHtml;
std::string heading = "WhatsApp Chat";
replacePlaceholder(html, "%HEADING%", heading);
replacePlaceholder(html, "%CONTACT%", contact);
replacePlaceholder(html, "%CONTACT_NAME%", contactName);
replacePlaceholder(html, "%MESSAGES%", messages);
return html;
}

void ChatExporterHtml::exportChats(const std::vector<WhatsappChat *> &chats, const std::string &filename)
{
std::ofstream file(filename.c_str());
if (!file)
{
throw Exception("could not open chat export file");
}

std::set<int> usedEmoticons;

std::string chatEntries;
for (auto i = chats.begin(); i != chats.end(); ++i) {
WhatsappChat *chat = *i;

if (i != chats.begin())
chatEntries += "\n";

chatEntries += exportChat(*chat, /* inout */ usedEmoticons);
}

std::string html = templateHtml;
std::string heading = "WhatsApp Chat";
replacePlaceholder(html, "%HEADING%", heading);
replacePlaceholder(html, "%TITLE%", heading + " " + contact);
replacePlaceholder(html, "%CONTACT%", contact);
replacePlaceholder(html, "%CONTACT_NAME%", contactName);
replacePlaceholder(html, "%MESSAGES%", messages);
std::string title = (chats.size() == 1) ? (heading + " " + chats[0]->getKey()) : heading;
replacePlaceholder(html, "%TITLE%", title);
replacePlaceholder(html, "%EMOTICON_STYLES%", buildEmoticonStyles(usedEmoticons));
replacePlaceholder(html, "%CHAT_ENTRIES%", chatEntries);

file << html;
}
6 changes: 4 additions & 2 deletions source/Exporters/ChatExporterHtml.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,17 @@ class ChatExporterHtml : public ChatExporter
private:
Settings &settings;
std::string templateHtml;
std::string entryTemplateHtml;

std::string buildMessages(WhatsappChat &chat, std::set<int> &usedEmoticons);
void replacePlaceholder(std::string &html, const std::string &placeholder, const std::string &text);
std::string convertMessageToHtml(WhatsappMessage &message, std::set<int> &usedEmoticons);
std::string buildEmoticonStyles(const std::set<int> &usedEmoticons);
std::string exportChat(WhatsappChat &chat, std::set<int> &usedEmoticons);

public:
ChatExporterHtml(Settings &settings, const std::string &templateHtml);
ChatExporterHtml(Settings &settings, const std::string &templateHtml, const std::string &entryTemplateHtml);
~ChatExporterHtml();

void exportChat(WhatsappChat &chat, const std::string &filename);
void exportChats(const std::vector<WhatsappChat *> &chats, const std::string &filename);
};
36 changes: 26 additions & 10 deletions source/Exporters/ChatExporterJson.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,19 +41,16 @@ void ChatExporterJson::addFilename(WhatsappMessage &message, rapidjson::Value &m
}
}

void ChatExporterJson::exportChat(WhatsappChat &chat, const std::string &filename)
void ChatExporterJson::exportChat(WhatsappChat &chat, rapidjson::Value &chatJson, rapidjson::Document &json)
{
rapidjson::Document json;
json.SetObject();

json.AddMember("key", chat.getKey(), json.GetAllocator());
chatJson.AddMember("key", chat.getKey(), json.GetAllocator());

if (chat.getSubject().length() > 0)
{
json.AddMember("subject", chat.getSubject(), json.GetAllocator());
chatJson.AddMember("subject", chat.getSubject(), json.GetAllocator());
}

json.AddMember("contactName", chat.getDisplayName(), json.GetAllocator());
chatJson.AddMember("contactName", chat.getDisplayName(), json.GetAllocator());

rapidjson::Value messagesJson(rapidjson::kArrayType);

Expand Down Expand Up @@ -143,11 +140,30 @@ void ChatExporterJson::exportChat(WhatsappChat &chat, const std::string &filenam
messagesJson.PushBack(messageJson, json.GetAllocator());
}

json.AddMember("messages", messagesJson, json.GetAllocator());
chatJson.AddMember("messages", messagesJson, json.GetAllocator());

}

void ChatExporterJson::exportChats(const std::vector<WhatsappChat *> &chats, const std::string &filename)
{
rapidjson::Document json;
json.SetObject();

rapidjson::Value chatsJson(rapidjson::kArrayType);

for (auto i = chats.begin(); i != chats.end(); ++i) {
WhatsappChat *chat = *i;

rapidjson::Value chatJson(rapidjson::kObjectType);
exportChat(*chat, chatJson, json);
chatsJson.PushBack(chatJson, json.GetAllocator());
}

json.AddMember("chats", chatsJson, json.GetAllocator());

rapidjson::StringBuffer buffer;
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buffer);
json.Accept(writer);
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buffer);
json.Accept(writer);

std::ofstream file(filename.c_str());
if (!file)
Expand Down
3 changes: 2 additions & 1 deletion source/Exporters/ChatExporterJson.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@ class ChatExporterJson : public ChatExporter
void addImageParameter(unsigned char *image, int size, rapidjson::Value &messageJson, rapidjson::Document &json);
void addFilename(WhatsappMessage &message, rapidjson::Value &messageJson, rapidjson::Document &json);
std::string findDisplayName(const std::string &key);
void exportChat(WhatsappChat &chat, rapidjson::Value &chatJson, rapidjson::Document &json);

public:
ChatExporterJson(Settings &settings);
~ChatExporterJson();

void exportChat(WhatsappChat &chat, const std::string &filename);
void exportChats(const std::vector<WhatsappChat *> &chats, const std::string &filename);
};
28 changes: 20 additions & 8 deletions source/Exporters/ChatExporterTxt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,8 @@ ChatExporterTxt::~ChatExporterTxt()
{
}

void ChatExporterTxt::exportChat(WhatsappChat &chat, const std::string &filename)
void ChatExporterTxt::exportChat(WhatsappChat &chat, std::ofstream &file)
{
std::ofstream file(filename.c_str());

if (!file)
{
throw Exception("could not open chat export file");
}

file << chat.getKey();

if (chat.getSubject().length() > 0)
Expand Down Expand Up @@ -117,3 +110,22 @@ void ChatExporterTxt::exportChat(WhatsappChat &chat, const std::string &filename
file << std::endl;
}
}

void ChatExporterTxt::exportChats(const std::vector<WhatsappChat *> &chats, const std::string &filename)
{
std::ofstream file(filename.c_str());

if (!file)
{
throw Exception("could not open chat export file");
}

for (auto i = chats.begin(); i != chats.end(); ++i) {
WhatsappChat *chat = *i;

if (i != chats.begin())
file << std::endl;

exportChat(*chat, file);
}
}
6 changes: 5 additions & 1 deletion source/Exporters/ChatExporterTxt.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <fstream>
#include <string>

#include "ChatExporter.h"
Expand All @@ -8,9 +9,12 @@ class WhatsappChat;

class ChatExporterTxt : public ChatExporter
{
private:
void exportChat(WhatsappChat &chat, std::ofstream &file);

public:
ChatExporterTxt();
~ChatExporterTxt();

void exportChat(WhatsappChat &chat, const std::string &filename);
void exportChats(const std::vector<WhatsappChat *> &chats, const std::string &filename);
};
Loading