mirror of https://github.com/procxx/kepka.git
				
				
				
			Simplest polls data export.
This commit is contained in:
		
							parent
							
								
									93c8e9aa1f
								
							
						
					
					
						commit
						ef1d38462f
					
				| 
						 | 
					@ -311,7 +311,8 @@ div.selected {
 | 
				
			||||||
    background-position: 12px 12px;
 | 
					    background-position: 12px 12px;
 | 
				
			||||||
    background-size: 24px 24px;
 | 
					    background-size: 24px 24px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.default .media .title {
 | 
					.default .media .title,
 | 
				
			||||||
 | 
					.default .media_poll .question {
 | 
				
			||||||
    padding-top: 4px;
 | 
					    padding-top: 4px;
 | 
				
			||||||
    font-size: 14px;
 | 
					    font-size: 14px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,6 +14,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 | 
				
			||||||
#include <QtCore/QDateTime>
 | 
					#include <QtCore/QDateTime>
 | 
				
			||||||
#include <QtCore/QRegularExpression>
 | 
					#include <QtCore/QRegularExpression>
 | 
				
			||||||
#include <QtGui/QImageReader>
 | 
					#include <QtGui/QImageReader>
 | 
				
			||||||
 | 
					#include <range/v3/view/all.hpp>
 | 
				
			||||||
 | 
					#include <range/v3/view/transform.hpp>
 | 
				
			||||||
 | 
					#include <range/v3/to_container.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace App { // Hackish..
 | 
					namespace App { // Hackish..
 | 
				
			||||||
QString formatPhone(QString phone);
 | 
					QString formatPhone(QString phone);
 | 
				
			||||||
| 
						 | 
					@ -507,6 +510,49 @@ Invoice ParseInvoice(const MTPDmessageMediaInvoice &data) {
 | 
				
			||||||
	return result;
 | 
						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(
 | 
					UserpicsSlice ParseUserpicsSlice(
 | 
				
			||||||
		const MTPVector<MTPPhoto> &data,
 | 
							const MTPVector<MTPPhoto> &data,
 | 
				
			||||||
		int baseIndex) {
 | 
							int baseIndex) {
 | 
				
			||||||
| 
						 | 
					@ -870,7 +916,7 @@ Media ParseMedia(
 | 
				
			||||||
		result.content = ParseGeoPoint(data.vgeo);
 | 
							result.content = ParseGeoPoint(data.vgeo);
 | 
				
			||||||
		result.ttl = data.vperiod.v;
 | 
							result.ttl = data.vperiod.v;
 | 
				
			||||||
	}, [&](const MTPDmessageMediaPoll &data) {
 | 
						}, [&](const MTPDmessageMediaPoll &data) {
 | 
				
			||||||
		//result.content = ParsePoll(data); // #TODO polls
 | 
							result.content = ParsePoll(data);
 | 
				
			||||||
	}, [](const MTPDmessageMediaEmpty &data) {});
 | 
						}, [](const MTPDmessageMediaEmpty &data) {});
 | 
				
			||||||
	return result;
 | 
						return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -178,6 +178,21 @@ struct Invoice {
 | 
				
			||||||
	int32 receiptMsgId = 0;
 | 
						int32 receiptMsgId = 0;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct Poll {
 | 
				
			||||||
 | 
						struct Answer {
 | 
				
			||||||
 | 
							Utf8String text;
 | 
				
			||||||
 | 
							QByteArray option;
 | 
				
			||||||
 | 
							int votes = 0;
 | 
				
			||||||
 | 
							bool my = false;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						uint64 id = 0;
 | 
				
			||||||
 | 
						Utf8String question;
 | 
				
			||||||
 | 
						std::vector<Answer> answers;
 | 
				
			||||||
 | 
						int totalVotes = 0;
 | 
				
			||||||
 | 
						bool closed = false;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct UserpicsSlice {
 | 
					struct UserpicsSlice {
 | 
				
			||||||
	std::vector<Photo> list;
 | 
						std::vector<Photo> list;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -299,6 +314,7 @@ struct Media {
 | 
				
			||||||
		Venue,
 | 
							Venue,
 | 
				
			||||||
		Game,
 | 
							Game,
 | 
				
			||||||
		Invoice,
 | 
							Invoice,
 | 
				
			||||||
 | 
							Poll,
 | 
				
			||||||
		UnsupportedMedia> content;
 | 
							UnsupportedMedia> content;
 | 
				
			||||||
	TimeId ttl = 0;
 | 
						TimeId ttl = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -621,6 +621,7 @@ private:
 | 
				
			||||||
	[[nodiscard]] QByteArray pushPhotoMedia(
 | 
						[[nodiscard]] QByteArray pushPhotoMedia(
 | 
				
			||||||
		const Data::Photo &data,
 | 
							const Data::Photo &data,
 | 
				
			||||||
		const QString &basePath);
 | 
							const QString &basePath);
 | 
				
			||||||
 | 
						[[nodiscard]] QByteArray pushPoll(const Data::Poll &data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	File _file;
 | 
						File _file;
 | 
				
			||||||
	bool _closed = false;
 | 
						bool _closed = false;
 | 
				
			||||||
| 
						 | 
					@ -1232,6 +1233,8 @@ QByteArray HtmlWriter::Wrap::pushMedia(
 | 
				
			||||||
	} else if (const auto photo = base::get_if<Data::Photo>(&content)) {
 | 
						} else if (const auto photo = base::get_if<Data::Photo>(&content)) {
 | 
				
			||||||
		Assert(!message.media.ttl);
 | 
							Assert(!message.media.ttl);
 | 
				
			||||||
		return pushPhotoMedia(*photo, basePath);
 | 
							return pushPhotoMedia(*photo, basePath);
 | 
				
			||||||
 | 
						} else if (const auto poll = base::get_if<Data::Poll>(&content)) {
 | 
				
			||||||
 | 
							return pushPoll(*poll);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	Assert(!content.has_value());
 | 
						Assert(!content.has_value());
 | 
				
			||||||
	return QByteArray();
 | 
						return QByteArray();
 | 
				
			||||||
| 
						 | 
					@ -1503,6 +1506,54 @@ QByteArray HtmlWriter::Wrap::pushPhotoMedia(
 | 
				
			||||||
	return result;
 | 
						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 " <span class=\"details\">"
 | 
				
			||||||
 | 
									+ votes(answer.votes)
 | 
				
			||||||
 | 
									+ "</span>";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return " <span class=\"details\">"
 | 
				
			||||||
 | 
								+ votes(answer.votes)
 | 
				
			||||||
 | 
								+ ", chosen vote</span>";
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						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(
 | 
					MediaData HtmlWriter::Wrap::prepareMediaData(
 | 
				
			||||||
		const Data::Message &message,
 | 
							const Data::Message &message,
 | 
				
			||||||
		const QString &basePath,
 | 
							const QString &basePath,
 | 
				
			||||||
| 
						 | 
					@ -1658,6 +1709,7 @@ MediaData HtmlWriter::Wrap::prepareMediaData(
 | 
				
			||||||
		result.title = data.title;
 | 
							result.title = data.title;
 | 
				
			||||||
		result.description = data.description;
 | 
							result.description = data.description;
 | 
				
			||||||
		result.status = Data::FormatMoneyAmount(data.amount, data.currency);
 | 
							result.status = Data::FormatMoneyAmount(data.amount, data.currency);
 | 
				
			||||||
 | 
						}, [](const Poll &data) {
 | 
				
			||||||
	}, [](const UnsupportedMedia &data) {
 | 
						}, [](const UnsupportedMedia &data) {
 | 
				
			||||||
		Unexpected("Unsupported message.");
 | 
							Unexpected("Unsupported message.");
 | 
				
			||||||
	}, [](std::nullopt_t) {});
 | 
						}, [](std::nullopt_t) {});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -574,6 +574,29 @@ QByteArray SerializeMessage(
 | 
				
			||||||
				? NumberToString(data.receiptMsgId)
 | 
									? NumberToString(data.receiptMsgId)
 | 
				
			||||||
				: QByteArray()) }
 | 
									: 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) {
 | 
						}, [](const UnsupportedMedia &data) {
 | 
				
			||||||
		Unexpected("Unsupported message.");
 | 
							Unexpected("Unsupported message.");
 | 
				
			||||||
	}, [](std::nullopt_t) {});
 | 
						}, [](std::nullopt_t) {});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -436,6 +436,19 @@ QByteArray SerializeMessage(
 | 
				
			||||||
				? "ID-" + NumberToString(data.receiptMsgId)
 | 
									? "ID-" + NumberToString(data.receiptMsgId)
 | 
				
			||||||
				: QByteArray()) }
 | 
									: 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) {
 | 
						}, [](const UnsupportedMedia &data) {
 | 
				
			||||||
		Unexpected("Unsupported message.");
 | 
							Unexpected("Unsupported message.");
 | 
				
			||||||
	}, [](std::nullopt_t) {});
 | 
						}, [](std::nullopt_t) {});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue