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 ¤cy); 708 Utf8String FormatFileSize(int64 size); 709 Utf8String FormatDuration(int64 seconds); 710 711 } // namespace Data 712 } // namespace Export 713