diff --git a/Telegram/Resources/export_html/css/style.css b/Telegram/Resources/export_html/css/style.css
index 74f36842d..52b90fd05 100644
--- a/Telegram/Resources/export_html/css/style.css
+++ b/Telegram/Resources/export_html/css/style.css
@@ -311,7 +311,8 @@ div.selected {
background-position: 12px 12px;
background-size: 24px 24px;
}
-.default .media .title {
+.default .media .title,
+.default .media_poll .question {
padding-top: 4px;
font-size: 14px;
}
diff --git a/Telegram/SourceFiles/export/data/export_data_types.cpp b/Telegram/SourceFiles/export/data/export_data_types.cpp
index 708fe89a7..6e09160ec 100644
--- a/Telegram/SourceFiles/export/data/export_data_types.cpp
+++ b/Telegram/SourceFiles/export/data/export_data_types.cpp
@@ -14,6 +14,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include
#include
#include
+#include
+#include
+#include
namespace App { // Hackish..
QString formatPhone(QString phone);
@@ -507,6 +510,49 @@ Invoice ParseInvoice(const MTPDmessageMediaInvoice &data) {
return result;
}
+Poll ParsePoll(const MTPDmessageMediaPoll &data) {
+ auto result = Poll();
+ data.vpoll.match([&](const MTPDpoll &poll) {
+ result.id = poll.vid.v;
+ result.question = ParseString(poll.vquestion);
+ result.closed = poll.is_closed();
+ result.answers = ranges::view::all(
+ poll.vanswers.v
+ ) | ranges::view::transform([](const MTPPollAnswer &answer) {
+ return answer.match([](const MTPDpollAnswer &answer) {
+ auto result = Poll::Answer();
+ result.text = ParseString(answer.vtext);
+ result.option = answer.voption.v;
+ return result;
+ });
+ }) | ranges::to_vector;
+ });
+ data.vresults.match([&](const MTPDpollResults &results) {
+ if (results.has_total_voters()) {
+ result.totalVotes = results.vtotal_voters.v;
+ }
+ if (results.has_results()) {
+ for (const auto &single : results.vresults.v) {
+ single.match([&](const MTPDpollAnswerVoters &voters) {
+ const auto &option = voters.voption.v;
+ const auto i = ranges::find(
+ result.answers,
+ voters.voption.v,
+ &Poll::Answer::option);
+ if (i == end(result.answers)) {
+ return;
+ }
+ i->votes = voters.vvoters.v;
+ if (voters.is_chosen()) {
+ i->my = true;
+ }
+ });
+ }
+ }
+ });
+ return result;
+}
+
UserpicsSlice ParseUserpicsSlice(
const MTPVector &data,
int baseIndex) {
@@ -870,7 +916,7 @@ Media ParseMedia(
result.content = ParseGeoPoint(data.vgeo);
result.ttl = data.vperiod.v;
}, [&](const MTPDmessageMediaPoll &data) {
- //result.content = ParsePoll(data); // #TODO polls
+ result.content = ParsePoll(data);
}, [](const MTPDmessageMediaEmpty &data) {});
return result;
}
diff --git a/Telegram/SourceFiles/export/data/export_data_types.h b/Telegram/SourceFiles/export/data/export_data_types.h
index 94e530467..8c91246be 100644
--- a/Telegram/SourceFiles/export/data/export_data_types.h
+++ b/Telegram/SourceFiles/export/data/export_data_types.h
@@ -178,6 +178,21 @@ struct Invoice {
int32 receiptMsgId = 0;
};
+struct Poll {
+ struct Answer {
+ Utf8String text;
+ QByteArray option;
+ int votes = 0;
+ bool my = false;
+ };
+
+ uint64 id = 0;
+ Utf8String question;
+ std::vector answers;
+ int totalVotes = 0;
+ bool closed = false;
+};
+
struct UserpicsSlice {
std::vector list;
};
@@ -299,6 +314,7 @@ struct Media {
Venue,
Game,
Invoice,
+ Poll,
UnsupportedMedia> content;
TimeId ttl = 0;
diff --git a/Telegram/SourceFiles/export/output/export_output_html.cpp b/Telegram/SourceFiles/export/output/export_output_html.cpp
index 615315d61..535d62a77 100644
--- a/Telegram/SourceFiles/export/output/export_output_html.cpp
+++ b/Telegram/SourceFiles/export/output/export_output_html.cpp
@@ -621,6 +621,7 @@ private:
[[nodiscard]] QByteArray pushPhotoMedia(
const Data::Photo &data,
const QString &basePath);
+ [[nodiscard]] QByteArray pushPoll(const Data::Poll &data);
File _file;
bool _closed = false;
@@ -1232,6 +1233,8 @@ QByteArray HtmlWriter::Wrap::pushMedia(
} else if (const auto photo = base::get_if(&content)) {
Assert(!message.media.ttl);
return pushPhotoMedia(*photo, basePath);
+ } else if (const auto poll = base::get_if(&content)) {
+ return pushPoll(*poll);
}
Assert(!content.has_value());
return QByteArray();
@@ -1503,6 +1506,54 @@ QByteArray HtmlWriter::Wrap::pushPhotoMedia(
return result;
}
+QByteArray HtmlWriter::Wrap::pushPoll(const Data::Poll &data) {
+ using namespace Data;
+
+ auto result = pushDiv("media_wrap clearfix");
+ result.append(pushDiv("media_poll"));
+ result.append(pushDiv("question bold"));
+ result.append(SerializeString(data.question));
+ result.append(popTag());
+ result.append(pushDiv("details"));
+ if (data.closed) {
+ result.append(SerializeString("Final results"));
+ } else {
+ result.append(SerializeString("Anonymous poll"));
+ }
+ result.append(popTag());
+ const auto votes = [](int count) {
+ if (count > 1) {
+ return NumberToString(count) + " votes";
+ } else if (count > 0) {
+ return NumberToString(count) + " vote";
+ }
+ return QByteArray("No votes");
+ };
+ const auto details = [&](const Poll::Answer &answer) {
+ if (!answer.votes) {
+ return QByteArray("");
+ } else if (!answer.my) {
+ return " "
+ + votes(answer.votes)
+ + "";
+ }
+ return " "
+ + votes(answer.votes)
+ + ", chosen vote";
+ };
+ for (const auto &answer : data.answers) {
+ result.append(pushDiv("answer"));
+ result.append("- " + SerializeString(answer.text) + details(answer));
+ result.append(popTag());
+ }
+ result.append(pushDiv("total details "));
+ result.append(votes(data.totalVotes));
+ result.append(popTag());
+ result.append(popTag());
+ result.append(popTag());
+ return result;
+}
+
MediaData HtmlWriter::Wrap::prepareMediaData(
const Data::Message &message,
const QString &basePath,
@@ -1658,6 +1709,7 @@ MediaData HtmlWriter::Wrap::prepareMediaData(
result.title = data.title;
result.description = data.description;
result.status = Data::FormatMoneyAmount(data.amount, data.currency);
+ }, [](const Poll &data) {
}, [](const UnsupportedMedia &data) {
Unexpected("Unsupported message.");
}, [](std::nullopt_t) {});
diff --git a/Telegram/SourceFiles/export/output/export_output_json.cpp b/Telegram/SourceFiles/export/output/export_output_json.cpp
index 5f8421e82..1c448c326 100644
--- a/Telegram/SourceFiles/export/output/export_output_json.cpp
+++ b/Telegram/SourceFiles/export/output/export_output_json.cpp
@@ -574,6 +574,29 @@ QByteArray SerializeMessage(
? NumberToString(data.receiptMsgId)
: QByteArray()) }
}));
+ }, [&](const Poll &data) {
+ context.nesting.push_back(Context::kObject);
+ const auto answers = ranges::view::all(
+ data.answers
+ ) | ranges::view::transform([&](const Poll::Answer &answer) {
+ context.nesting.push_back(Context::kArray);
+ auto result = SerializeObject(context, {
+ { "text", SerializeString(answer.text) },
+ { "voters", NumberToString(answer.votes) },
+ { "chosen", answer.my ? "true" : "false" },
+ });
+ context.nesting.pop_back();
+ return result;
+ }) | ranges::to_vector;
+ const auto serialized = SerializeArray(context, answers);
+ context.nesting.pop_back();
+
+ pushBare("poll", SerializeObject(context, {
+ { "question", SerializeString(data.question) },
+ { "closed", data.closed ? "true" : "false" },
+ { "total_voters", NumberToString(data.totalVotes) },
+ { "answers", serialized }
+ }));
}, [](const UnsupportedMedia &data) {
Unexpected("Unsupported message.");
}, [](std::nullopt_t) {});
diff --git a/Telegram/SourceFiles/export/output/export_output_text.cpp b/Telegram/SourceFiles/export/output/export_output_text.cpp
index c80cb5315..b5fec1cc3 100644
--- a/Telegram/SourceFiles/export/output/export_output_text.cpp
+++ b/Telegram/SourceFiles/export/output/export_output_text.cpp
@@ -436,6 +436,19 @@ QByteArray SerializeMessage(
? "ID-" + NumberToString(data.receiptMsgId)
: QByteArray()) }
}));
+ }, [&](const Poll &data) {
+ push("Poll", SerializeKeyValue({
+ { "Question", data.question },
+ { "Closed", data.closed ? QByteArray("Yes") : QByteArray() },
+ { "Votes", NumberToString(data.totalVotes) },
+ }));
+ for (const auto &answer : data.answers) {
+ push("Answer", SerializeKeyValue({
+ { "Text", answer.text },
+ { "Votes", NumberToString(answer.votes) },
+ { "Chosen", answer.my ? QByteArray("Yes") : QByteArray() }
+ }));
+ }
}, [](const UnsupportedMedia &data) {
Unexpected("Unsupported message.");
}, [](std::nullopt_t) {});