1 /*
2 This file is part of Telegram Desktop,
3 the official desktop application for the Telegram messaging service.
4 
5 For license and copyright information please follow this link:
6 https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
7 */
8 #pragma once
9 
10 #include "scheme.h"
11 #include "base/optional.h"
12 #include "base/variant.h"
13 #include "data/data_peer_id.h"
14 
15 #include <QtCore/QSize>
16 #include <QtCore/QString>
17 #include <QtCore/QByteArray>
18 
19 #include <vector>
20 
21 namespace Export {
22 struct Settings;
23 namespace Data {
24 
25 using Utf8String = QByteArray;
26 
27 int PeerColorIndex(BareId bareId);
28 BareId PeerToBareId(PeerId peerId);
29 int PeerColorIndex(PeerId peerId);
30 int ApplicationColorIndex(int applicationId);
31 int DomainApplicationId(const Utf8String &data);
32 
33 Utf8String ParseString(const MTPstring &data);
34 
35 Utf8String FillLeft(const Utf8String &data, int length, char filler);
36 
37 template <typename Type>
38 inline auto NumberToString(Type value, int length = 0, char filler = '0')
39 -> std::enable_if_t<std::is_arithmetic_v<Type>, Utf8String> {
40 	const auto result = std::to_string(value);
41 	return FillLeft(
42 		Utf8String(result.data(), int(result.size())),
43 		length,
44 		filler).replace(',', '.');
45 }
46 
47 struct UserpicsInfo {
48 	int count = 0;
49 };
50 
51 struct FileLocation {
52 	int dcId = 0;
53 	MTPInputFileLocation data;
54 
55 	explicit operator bool() const {
56 		return dcId != 0;
57 	}
58 };
59 
60 bool RefreshFileReference(FileLocation &to, const FileLocation &from);
61 
62 struct File {
63 	enum class SkipReason {
64 		None,
65 		Unavailable,
66 		FileType,
67 		FileSize,
68 		DateLimits,
69 	};
70 	FileLocation location;
71 	int size = 0;
72 	QByteArray content;
73 
74 	QString suggestedPath;
75 
76 	QString relativePath;
77 	SkipReason skipReason = SkipReason::None;
78 };
79 
80 struct Image {
81 	int width = 0;
82 	int height = 0;
83 	File file;
84 };
85 
86 std::pair<QString, QSize> WriteImageThumb(
87 	const QString &basePath,
88 	const QString &largePath,
89 	Fn<QSize(QSize)> convertSize,
90 	std::optional<QByteArray> format = std::nullopt,
91 	std::optional<int> quality = std::nullopt,
92 	const QString &postfix = "_thumb");
93 
94 QString WriteImageThumb(
95 	const QString &basePath,
96 	const QString &largePath,
97 	int width,
98 	int height,
99 	const QString &postfix = "_thumb");
100 
101 struct ContactInfo {
102 	UserId userId = 0;
103 	Utf8String firstName;
104 	Utf8String lastName;
105 	Utf8String phoneNumber;
106 	TimeId date = 0;
107 
108 	Utf8String name() const;
109 };
110 
111 ContactInfo ParseContactInfo(const MTPUser &data);
112 int ContactColorIndex(const ContactInfo &data);
113 
114 struct Photo {
115 	uint64 id = 0;
116 	TimeId date = 0;
117 
118 	Image image;
119 };
120 
121 struct Document {
122 	uint64 id = 0;
123 	TimeId date = 0;
124 
125 	File file;
126 	Image thumb;
127 
128 	Utf8String name;
129 	Utf8String mime;
130 	int width = 0;
131 	int height = 0;
132 
133 	Utf8String stickerEmoji;
134 	Utf8String songPerformer;
135 	Utf8String songTitle;
136 	int duration = 0;
137 
138 	bool isSticker = false;
139 	bool isAnimated = false;
140 	bool isVideoMessage = false;
141 	bool isVoiceMessage = false;
142 	bool isVideoFile = false;
143 	bool isAudioFile = false;
144 };
145 
146 struct SharedContact {
147 	ContactInfo info;
148 	File vcard;
149 };
150 
151 struct GeoPoint {
152 	float64 latitude = 0.;
153 	float64 longitude = 0.;
154 	bool valid = false;
155 };
156 
157 struct Venue {
158 	GeoPoint point;
159 	Utf8String title;
160 	Utf8String address;
161 };
162 
163 struct Game {
164 	uint64 id = 0;
165 	Utf8String shortName;
166 	Utf8String title;
167 	Utf8String description;
168 
169 	UserId botId = 0;
170 };
171 
172 struct Invoice {
173 	Utf8String title;
174 	Utf8String description;
175 	Utf8String currency;
176 	uint64 amount = 0;
177 	int32 receiptMsgId = 0;
178 };
179 
180 struct Poll {
181 	struct Answer {
182 		Utf8String text;
183 		QByteArray option;
184 		int votes = 0;
185 		bool my = false;
186 	};
187 
188 	uint64 id = 0;
189 	Utf8String question;
190 	std::vector<Answer> answers;
191 	int totalVotes = 0;
192 	bool closed = false;
193 };
194 
195 struct UserpicsSlice {
196 	std::vector<Photo> list;
197 };
198 
199 UserpicsSlice ParseUserpicsSlice(
200 	const MTPVector<MTPPhoto> &data,
201 	int baseIndex);
202 
203 struct User {
204 	PeerId id() const;
205 
206 	BareId bareId = 0;
207 	ContactInfo info;
208 	Utf8String username;
209 	bool isBot = false;
210 	bool isSelf = false;
211 	bool isReplies = false;
212 
213 	MTPInputUser input = MTP_inputUserEmpty();
214 
215 	Utf8String name() const;
216 };
217 
218 User ParseUser(const MTPUser &data);
219 std::map<UserId, User> ParseUsersList(const MTPVector<MTPUser> &data);
220 
221 struct Chat {
222 	PeerId id() const;
223 
224 	BareId bareId = 0;
225 	ChannelId migratedToChannelId = 0;
226 	Utf8String title;
227 	Utf8String username;
228 	bool isBroadcast = false;
229 	bool isSupergroup = false;
230 
231 	MTPInputPeer input = MTP_inputPeerEmpty();
232 };
233 
234 Chat ParseChat(const MTPChat &data);
235 std::map<PeerId, Chat> ParseChatsList(const MTPVector<MTPChat> &data);
236 
237 struct Peer {
238 	PeerId id() const;
239 	Utf8String name() const;
240 	MTPInputPeer input() const;
241 
242 	const User *user() const;
243 	const Chat *chat() const;
244 
245 	std::variant<User, Chat> data;
246 
247 };
248 
249 std::map<PeerId, Peer> ParsePeersLists(
250 	const MTPVector<MTPUser> &users,
251 	const MTPVector<MTPChat> &chats);
252 
253 struct PersonalInfo {
254 	User user;
255 	Utf8String bio;
256 };
257 
258 PersonalInfo ParsePersonalInfo(const MTPUserFull &data);
259 
260 struct TopPeer {
261 	Peer peer;
262 	float64 rating = 0.;
263 };
264 
265 struct ContactsList {
266 	std::vector<ContactInfo> list;
267 	std::vector<TopPeer> correspondents;
268 	std::vector<TopPeer> inlineBots;
269 	std::vector<TopPeer> phoneCalls;
270 };
271 
272 ContactsList ParseContactsList(const MTPcontacts_Contacts &data);
273 ContactsList ParseContactsList(const MTPVector<MTPSavedContact> &data);
274 std::vector<int> SortedContactsIndices(const ContactsList &data);
275 bool AppendTopPeers(ContactsList &to, const MTPcontacts_TopPeers &data);
276 
277 struct Session {
278 	int applicationId = 0;
279 	Utf8String platform;
280 	Utf8String deviceModel;
281 	Utf8String systemVersion;
282 	Utf8String applicationName;
283 	Utf8String applicationVersion;
284 	TimeId created = 0;
285 	TimeId lastActive = 0;
286 	Utf8String ip;
287 	Utf8String country;
288 	Utf8String region;
289 };
290 
291 struct WebSession {
292 	Utf8String botUsername;
293 	Utf8String domain;
294 	Utf8String browser;
295 	Utf8String platform;
296 	TimeId created = 0;
297 	TimeId lastActive = 0;
298 	Utf8String ip;
299 	Utf8String region;
300 };
301 
302 struct SessionsList {
303 	std::vector<Session> list;
304 	std::vector<WebSession> webList;
305 };
306 
307 SessionsList ParseSessionsList(const MTPaccount_Authorizations &data);
308 SessionsList ParseWebSessionsList(const MTPaccount_WebAuthorizations &data);
309 
310 struct UnsupportedMedia {
311 };
312 
313 struct Media {
314 	std::variant<
315 		v::null_t,
316 		Photo,
317 		Document,
318 		SharedContact,
319 		GeoPoint,
320 		Venue,
321 		Game,
322 		Invoice,
323 		Poll,
324 		UnsupportedMedia> content;
325 	TimeId ttl = 0;
326 
327 	File &file();
328 	const File &file() const;
329 	Image &thumb();
330 	const Image &thumb() const;
331 };
332 
333 struct ParseMediaContext {
334 	PeerId selfPeerId = 0;
335 	int photos = 0;
336 	int audios = 0;
337 	int videos = 0;
338 	int files = 0;
339 	int contacts = 0;
340 	UserId botId = 0;
341 };
342 
343 Media ParseMedia(
344 	ParseMediaContext &context,
345 	const MTPMessageMedia &data,
346 	const QString &folder,
347 	TimeId date);
348 
349 struct ActionChatCreate {
350 	Utf8String title;
351 	std::vector<UserId> userIds;
352 };
353 
354 struct ActionChatEditTitle {
355 	Utf8String title;
356 };
357 
358 struct ActionChatEditPhoto {
359 	Photo photo;
360 };
361 
362 struct ActionChatDeletePhoto {
363 };
364 
365 struct ActionChatAddUser {
366 	std::vector<UserId> userIds;
367 };
368 
369 struct ActionChatDeleteUser {
370 	UserId userId = 0;
371 };
372 
373 struct ActionChatJoinedByLink {
374 	UserId inviterId = 0;
375 };
376 
377 struct ActionChannelCreate {
378 	Utf8String title;
379 };
380 
381 struct ActionChatMigrateTo {
382 	ChannelId channelId = 0;
383 };
384 
385 struct ActionChannelMigrateFrom {
386 	Utf8String title;
387 	ChatId chatId = 0;
388 };
389 
390 struct ActionPinMessage {
391 };
392 
393 struct ActionHistoryClear {
394 };
395 
396 struct ActionGameScore {
397 	uint64 gameId = 0;
398 	int score = 0;
399 };
400 
401 struct ActionPaymentSent {
402 	Utf8String currency;
403 	uint64 amount = 0;
404 };
405 
406 struct ActionPhoneCall {
407 	enum class DiscardReason {
408 		Unknown,
409 		Missed,
410 		Disconnect,
411 		Hangup,
412 		Busy,
413 	};
414 	DiscardReason discardReason = DiscardReason::Unknown;
415 	int duration = 0;
416 };
417 
418 struct ActionScreenshotTaken {
419 };
420 
421 struct ActionCustomAction {
422 	Utf8String message;
423 };
424 
425 struct ActionBotAllowed {
426 	Utf8String domain;
427 };
428 
429 struct ActionSecureValuesSent {
430 	enum class Type {
431 		PersonalDetails,
432 		Passport,
433 		DriverLicense,
434 		IdentityCard,
435 		InternalPassport,
436 		Address,
437 		UtilityBill,
438 		BankStatement,
439 		RentalAgreement,
440 		PassportRegistration,
441 		TemporaryRegistration,
442 		Phone,
443 		Email,
444 	};
445 	std::vector<Type> types;
446 };
447 
448 struct ActionContactSignUp {
449 };
450 
451 struct ActionPhoneNumberRequest {
452 };
453 
454 struct ActionGeoProximityReached {
455 	PeerId fromId = 0;
456 	PeerId toId = 0;
457 	int distance = 0;
458 	bool fromSelf = false;
459 	bool toSelf = false;
460 };
461 
462 struct ActionGroupCall {
463 	int duration = 0;
464 };
465 
466 struct ActionInviteToGroupCall {
467 	std::vector<UserId> userIds;
468 };
469 
470 struct ActionSetMessagesTTL {
471 	TimeId period = 0;
472 };
473 
474 struct ActionGroupCallScheduled {
475 	TimeId date = 0;
476 };
477 
478 struct ActionSetChatTheme {
479 	QString emoji;
480 };
481 
482 struct ActionChatJoinedByRequest {
483 };
484 
485 struct ServiceAction {
486 	std::variant<
487 		v::null_t,
488 		ActionChatCreate,
489 		ActionChatEditTitle,
490 		ActionChatEditPhoto,
491 		ActionChatDeletePhoto,
492 		ActionChatAddUser,
493 		ActionChatDeleteUser,
494 		ActionChatJoinedByLink,
495 		ActionChannelCreate,
496 		ActionChatMigrateTo,
497 		ActionChannelMigrateFrom,
498 		ActionPinMessage,
499 		ActionHistoryClear,
500 		ActionGameScore,
501 		ActionPaymentSent,
502 		ActionPhoneCall,
503 		ActionScreenshotTaken,
504 		ActionCustomAction,
505 		ActionBotAllowed,
506 		ActionSecureValuesSent,
507 		ActionContactSignUp,
508 		ActionPhoneNumberRequest,
509 		ActionGeoProximityReached,
510 		ActionGroupCall,
511 		ActionInviteToGroupCall,
512 		ActionSetMessagesTTL,
513 		ActionGroupCallScheduled,
514 		ActionSetChatTheme,
515 		ActionChatJoinedByRequest> content;
516 };
517 
518 ServiceAction ParseServiceAction(
519 	ParseMediaContext &context,
520 	const MTPMessageAction &data,
521 	const QString &mediaFolder);
522 
523 struct TextPart {
524 	enum class Type {
525 		Text,
526 		Unknown,
527 		Mention,
528 		Hashtag,
529 		BotCommand,
530 		Url,
531 		Email,
532 		Bold,
533 		Italic,
534 		Code,
535 		Pre,
536 		TextUrl,
537 		MentionName,
538 		Phone,
539 		Cashtag,
540 		Underline,
541 		Strike,
542 		Blockquote,
543 		BankCard,
544 	};
545 	Type type = Type::Text;
546 	Utf8String text;
547 	Utf8String additional;
548 };
549 
550 struct MessageId {
551 	ChannelId channelId;
552 	int32 msgId = 0;
553 };
554 
555 inline bool operator==(MessageId a, MessageId b) {
556 	return (a.channelId == b.channelId) && (a.msgId == b.msgId);
557 }
558 inline bool operator!=(MessageId a, MessageId b) {
559 	return !(a == b);
560 }
561 inline bool operator<(MessageId a, MessageId b) {
562 	return (a.channelId < b.channelId)
563 		|| (a.channelId == b.channelId && a.msgId < b.msgId);
564 }
565 inline bool operator>(MessageId a, MessageId b) {
566 	return (b < a);
567 }
568 inline bool operator<=(MessageId a, MessageId b) {
569 	return !(b < a);
570 }
571 inline bool operator>=(MessageId a, MessageId b) {
572 	return !(a < b);
573 }
574 
575 struct Message {
576 	int32 id = 0;
577 	TimeId date = 0;
578 	TimeId edited = 0;
579 	PeerId fromId = 0;
580 	PeerId peerId = 0;
581 	PeerId selfId = 0;
582 	PeerId forwardedFromId = 0;
583 	Utf8String forwardedFromName;
584 	TimeId forwardedDate = 0;
585 	bool forwarded = false;
586 	bool showForwardedAsOriginal = false;
587 	PeerId savedFromChatId = 0;
588 	Utf8String signature;
589 	UserId viaBotId = 0;
590 	int32 replyToMsgId = 0;
591 	PeerId replyToPeerId = 0;
592 	std::vector<TextPart> text;
593 	Media media;
594 	ServiceAction action;
595 	bool out = false;
596 
597 	File &file();
598 	const File &file() const;
599 	Image &thumb();
600 	const Image &thumb() const;
601 };
602 
603 struct FileOrigin {
604 	int split = 0;
605 	MTPInputPeer peer;
606 	int32 messageId = 0;
607 };
608 
609 Message ParseMessage(
610 	ParseMediaContext &context,
611 	const MTPMessage &data,
612 	const QString &mediaFolder);
613 std::map<MessageId, Message> ParseMessagesList(
614 	PeerId selfId,
615 	const MTPVector<MTPMessage> &data,
616 	const QString &mediaFolder);
617 
618 struct DialogInfo {
619 	enum class Type {
620 		Unknown,
621 		Self,
622 		Replies,
623 		Personal,
624 		Bot,
625 		PrivateGroup,
626 		PrivateSupergroup,
627 		PublicSupergroup,
628 		PrivateChannel,
629 		PublicChannel,
630 	};
631 	Type type = Type::Unknown;
632 	Utf8String name;
633 	Utf8String lastName;
634 
635 	MTPInputPeer input = MTP_inputPeerEmpty();
636 	int32 topMessageId = 0;
637 	TimeId topMessageDate = 0;
638 	PeerId peerId = 0;
639 
640 	MTPInputPeer migratedFromInput = MTP_inputPeerEmpty();
641 	ChannelId migratedToChannelId = 0;
642 
643 	// User messages splits which contained that dialog.
644 	std::vector<int> splits;
645 
646 	// Filled after the whole dialogs list is accumulated.
647 	bool onlyMyMessages = false;
648 	bool isLeftChannel = false;
649 	QString relativePath;
650 
651 	// Filled when requesting dialog messages.
652 	std::vector<int> messagesCountPerSplit;
653 };
654 
655 struct DialogsInfo {
656 	DialogInfo *item(int index);
657 	const DialogInfo *item(int index) const;
658 
659 	std::vector<DialogInfo> chats;
660 	std::vector<DialogInfo> left;
661 };
662 
663 DialogInfo::Type DialogTypeFromChat(const Chat &chat);
664 
665 DialogsInfo ParseDialogsInfo(const MTPmessages_Dialogs &data);
666 DialogsInfo ParseDialogsInfo(
667 	const MTPInputPeer &singlePeer,
668 	const MTPVector<MTPUser> &data);
669 DialogsInfo ParseDialogsInfo(
670 	const MTPInputPeer &singlePeer,
671 	const MTPmessages_Chats &data);
672 DialogsInfo ParseLeftChannelsInfo(const MTPmessages_Chats &data);
673 bool AddMigrateFromSlice(
674 	DialogInfo &to,
675 	const DialogInfo &from,
676 	int splitIndex,
677 	int splitsCount);
678 void FinalizeDialogsInfo(DialogsInfo &info, const Settings &settings);
679 
680 struct MessagesSlice {
681 	std::vector<Message> list;
682 	std::map<PeerId, Peer> peers;
683 };
684 
685 MessagesSlice ParseMessagesSlice(
686 	ParseMediaContext &context,
687 	const MTPVector<MTPMessage> &data,
688 	const MTPVector<MTPUser> &users,
689 	const MTPVector<MTPChat> &chats,
690 	const QString &mediaFolder);
691 MessagesSlice AdjustMigrateMessageIds(MessagesSlice slice);
692 
693 bool SingleMessageBefore(
694 	const MTPmessages_Messages &data,
695 	TimeId date);
696 bool SingleMessageAfter(
697 	const MTPmessages_Messages &data,
698 	TimeId date);
699 bool SkipMessageByDate(const Message &message, const Settings &settings);
700 
701 Utf8String FormatPhoneNumber(const Utf8String &phoneNumber);
702 Utf8String FormatDateTime(
703 	TimeId date,
704 	QChar dateSeparator = QChar('.'),
705 	QChar timeSeparator = QChar(':'),
706 	QChar separator = QChar(' '));
707 Utf8String FormatMoneyAmount(int64 amount, const Utf8String &currency);
708 Utf8String FormatFileSize(int64 size);
709 Utf8String FormatDuration(int64 seconds);
710 
711 } // namespace Data
712 } // namespace Export
713